package ai.people.netmon.framework.domain.graph.enums;

import ai.people.netmon.framework.constant.GraphConstant;
import ai.people.netmon.framework.domain.archives.annotation.CheckEmpty;
import ai.people.netmon.framework.domain.graph.tags.*;
import ai.people.netmon.utils.StringPool;
import com.google.common.base.CaseFormat;

import java.lang.reflect.Field;
import java.util.*;

/**
 * 图标签枚举
 *
 * @author zhenglin
 * @date 2022/4/25
 */
public enum GraphTagEnum {
    /**
     * reddit版块
     */
    REDDIT_SECTION("reddit_section", "reddit_section", null, RedditSectionTag.class),
    /**
     * 重点账号
     */
    KEY_ACCOUNT("key_account", "key_account", null, KeyAccountTag.class),
    /**
     * 重点账号-辅助落查
     */
    KEY_ACCOUNT_SEARCH("key_account_search", "key_account_search", null, KeyAccountSearchTag.class),
    /**
     * 档案
     */
    PERSON_ARCHIVES("person_archives", "archives", null, PersonArchivesTag.class),
    /**
     * 团伙
     */
    GANG_GROUP("gang_group", "gang_group", null, GangGroupTag.class),
    /**
     * 团伙成员
     */
    GANG_GROUP_MEMBERS("gang_group_members", "gang_members", null, GangGroupMembersTag.class),
    /**
     * 身份证
     */
    ID_NUMBER("id_number", "idcard", null, IdNumberTag.class),
    /**
     * 护照
     */
    PASSPORT("passport", "passport", null, PassportTag.class),
    /**
     * 电话
     */
    PHONE("phone", "phone", "number", PhoneTag.class),
    /**
     * 银行
     */
    BANK_ACCOUNT("bank_account", "bank", null, BankAccountTag.class),
    /**
     * 车牌
     */
    PLATE_NUMBER("plate_number", "plate", "plate", PlateNumberTag.class),
    /**
     * 电子邮件
     */
    EMAIL("email", "email", "email", EmailTag.class),
    /**
     * 教育经历
     */
    EDUCATION("education", "education", "school", EducationTag.class),
    /**
     * 工作经历
     */
    WORK("work", "work", "company", WorkTag.class),
    /**
     * 公司
     */
    COMPANY("company", "company", "name,unified_social_credit_code", CompanyTag.class),
    /**
     * 电报
     */
    TELEGRAM("telegram", "telegram", "user_name", TelegramTag.class),
    /**
     * 电报群
     */
    TELEGRAM_GROUP("telegram_group", "telegram_group", null, TelegramGroupTag.class),
    /**
     * 脸谱网
     */
    FACEBOOK("facebook", "facebook", "user_name", FacebookTag.class),
    /**
     * 推特
     */
    TWITTER("twitter", "twitter", "user_name", TwitterTag.class),
    /**
     * reddit
     */
    REDDIT("reddit", "reddit", "user_name", RedditTag.class),
    /**
     * whatsapp
     */
    WHATSAPP("whatsapp", "whatsapp", "user_name", WhatsappTag.class),
    /**
     * youtube
     */
    YOUTUBE("youtube", "youtube", "user_name", YoutubeTag.class),
    /**
     * 微博
     */
    WEIBO("weibo", "weibo", "user_name", WeiboTag.class),
    /**
     * line
     */
    LINE("line", "line", "user_name", LineTag.class),
    /**
     * 信号
     */
    SIGNAL("signal", "signal", "user_name", SignalTag.class),
    /**
     * gettr
     */
    GETTR("gettr", "gettr", "user_name", GettrTag.class),
    /**
     * instagram
     */
    INSTAGRAM("instagram", "instagram", "user_name", InstagramTag.class),
    /**
     * qq
     */
    QQ("qq", "qq", "user_name", QqTag.class),
    /**
     * tiktok
     */
    TIKTOK("tiktok", "tiktok", "user_name", TiktokTag.class),
    /**
     * vk
     */
    VK("vk", "vk", "user_name", VkTag.class),
    /**
     * linkedin
     */
    LINKEDIN("linkedin", "linkedin", "user_name", LinkedinTag.class),
    /**
     * ethereum
     */
    ETHEREUM("ethereum", "ethereum", GraphConstant.MD5 + "address", EthereumTag.class),
    /**
     * 比特币
     */
    BITCOIN("bitcoin", "bitcoin", GraphConstant.MD5 + "address", BitcoinTag.class),

    ;

    /**
     * 图中的tag 名
     */
    public final String tagName;
    /**
     * vid前缀
     */
    public final String vidPrefix;
    /**
     * vid属性键
     */
    public final String vidPropertiesKey;
    /**
     * 类
     */
    public final Class<?> clazz;

    GraphTagEnum(String tagName, String vidPrefix, String vidPropertiesKey, Class<?> aClass) {
        this.tagName = tagName;
        this.vidPrefix = vidPrefix;
        this.vidPropertiesKey = vidPropertiesKey;
        this.clazz = aClass;
    }

    public static GraphTagEnum getByTagName(String tagName) {
        for (GraphTagEnum graphTagEnum : GraphTagEnum.values()) {
            if (graphTagEnum.tagName.equals(tagName)) {
                return graphTagEnum;
            }
        }
        return null;
    }

    /**
     * 通过tag name 获取配置的类
     *
     * @param tagName 标签名
     * @return {@link Class}  配置的类
     */
    public static Class<?> getClassByTagName(String tagName) {
        for (GraphTagEnum graphTagEnum : GraphTagEnum.values()) {
            if (graphTagEnum.tagName.equals(tagName)) {
                return graphTagEnum.clazz;
            }
        }
        return null;
    }

    /**
     * 通过tagName获取该配置类字段上是否标注了非空注解
     *
     * @param tagName 标签名
     * @return {@link Map}<{@link String}, {@link String}> key:字段名, value:字段注解
     */
    public static Map<String, String> getClassNotEmptyFieldsByTagName(String tagName) {
        Map<String, String> map = new HashMap<>();
        for (GraphTagEnum graphTagEnum : GraphTagEnum.values()) {
            if (graphTagEnum.tagName.equals(tagName)) {
                for (Field declaredField : graphTagEnum.clazz.getDeclaredFields()) {
                    handle(map, declaredField);
                }
                if (Objects.nonNull(graphTagEnum.clazz.getSuperclass())) {
                    for (Field declaredField : graphTagEnum.clazz.getSuperclass().getDeclaredFields()) {
                        handle(map, declaredField);
                    }
                }
            }
        }
        return map;
    }

    private static void handle(Map<String, String> map, Field declaredField) {
        if (declaredField.isAnnotationPresent(CheckEmpty.class)) {
            declaredField.setAccessible(true);
            CheckEmpty annotation = declaredField.getAnnotation(CheckEmpty.class);
            String message = annotation.message();
            map.put(CaseFormat.LOWER_CAMEL.to(CaseFormat.LOWER_UNDERSCORE, declaredField.getName()), message);
        }
    }

    public List<String> vidPropertiesKeys() {
        return Arrays.asList(vidPropertiesKey.split(StringPool.COMMA));
    }
}
